package main

import (
	"context"
	"flag"
	"fmt"

	"time"

	pb "helloworld/api/server/v1"

	"gitee.com/carlzyhuang/framework/app"
	"gitee.com/carlzyhuang/framework/log"
	"gitee.com/carlzyhuang/framework/routing"
	"gitee.com/carlzyhuang/framework/rpc"
	"gitee.com/carlzyhuang/framework/rpc/client"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"

	_ "gitee.com/carlzyhuang/framework/naming/etcd"
)

var (
	// flagconf is the config flag.
	flagconf string
	// Version is the version of the compiled software.
	Version string
)

func init() {
	flag.StringVar(&flagconf, "conf", "cli_config.yaml", "config path, eg: -conf cli_config.yaml")
	rpc.Version = Version
}

const (
	address        = "localhost:9000"
	defServiceName = "helloworld"
)

// 方式一： 直连
func NewClientByTarget(addr string) (cli pb.GreeterClient, testCli pb.TestClient, free func()) {
	// Set up a connection to the server.
	//conn, err := grpc.DialInsecure(address, grpc.WithInsecure(), grpc.WithBlock())
	conn, err := grpc.NewClient(addr,
		grpc.WithTransportCredentials(insecure.NewCredentials()),
	)
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	free = func() {
		conn.Close()
	}
	cli = pb.NewGreeterClient(conn)
	testCli = pb.NewTestClient(conn)
	return
}

// 方式二： 使用注册中心
func NewClient(ctx context.Context, name string) (cli pb.GreeterClient, testCli pb.TestClient, free func()) {
	conn, err := client.NewClient(ctx, name)
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	free = func() {
		conn.Close()
	}
	cli = pb.NewGreeterClient(conn)
	testCli = pb.NewTestClient(conn)
	return
}

// 方式三： 使用配置注册
func RegisterRouting() {
	routing.RegisterByRand(pb.Greeter_ServiceDesc.ServiceName, func(o ...client.Option) pb.GreeterClient {
		conn, err := client.NewClient(context.Background(), fmt.Sprintf("discovery:///%s", defServiceName), o...)
		if err != nil {
			return nil
		}
		return pb.NewGreeterClient(conn)
	})

	routing.RegisterByRand(pb.Test_ServiceDesc.ServiceName, func(o ...client.Option) pb.TestClient {
		conn, err := client.NewClient(context.Background(), fmt.Sprintf("discovery:///%s", defServiceName), o...)
		if err != nil {
			return nil
		}
		return pb.NewTestClient(conn)
	})
}

func main() {
	flag.Parse()

	if err := app.Load(flagconf); err != nil {
		log.Anyf("load config: %s", err)
		return
	}

	RegisterRouting()

	name := defServiceName
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()

	//1 方式一：直接用grpc客户端直连 greeter, tester, release := NewClientByTarget(address)
	//2 方式二：用framework封装的客户端直连 greeter, tester, release := NewClient(ctx, address)
	//3 方式三：用framework封装的etcd服务发现连接	greeter, tester, release := NewClient(ctx, fmt.Sprintf("discovery:///%s", name))
	// defer release()

	//4 方式四：用routing封装的库
	greeter, _ := routing.NewClient[pb.GreeterClient](ctx, 0)
	r, err := greeter.SayHello(ctx, &pb.HelloRequest{Name: name})
	if err != nil {
		log.Fatalf("could not greet: %v", err)
	}
	log.Infof("Greeting: %s", r)

	tester, _ := routing.NewClient[pb.TestClient](ctx, 0)
	r, err = tester.Testing(ctx, &pb.HelloRequest{Name: name})
	if err != nil {
		log.Fatalf("could not greet: %v", err)
	}
	log.Infof("testing: %s ", r)
}
